/* eslint-disable max-params */
import { YForm, YInterception, YItemConfig, YItemRow } from '../interface';
import ItemConfig from './ItemConfig';
import ItemRowList from './ItemRowList';
import ItemText from './ItemText';

type NodeType = ItemRow | ItemConfig | ItemRowList | ItemText | null;

export default class ItemRow {
  itemRowList: ItemRowList;
  data: YItemRow;
  next: NodeType;
  prev: NodeType;
  constructor(
    data: YItemRow = { children: [] },
    next: NodeType = null,
    prev: NodeType = null,
    public form: YForm
  ) {
    this.data = data;
    this.next = next;
    this.prev = prev;
    const itemRowList = new ItemRowList(null, null, this.form);
    if (this.data.children) {
      this.data.children.forEach((item: any) => itemRowList.add(item));
    }
    this.itemRowList = itemRowList;
  }

  getConfig(interception?: YInterception) {
    let config: any = Object.assign({}, this.data);
    if (interception) {
      if (interception?.itemConfig?.['*']) {
        config = interception.itemConfig['*'](config);
      }
      if (interception?.itemConfig?.row) {
        config = interception.itemConfig.row(config);
      }
    }
    const children = this.data.children || [];
    if (children.length) {
      config.children = this.itemRowList.getConfig(interception);
    }

    return config;
  }

  // 设置经用效果
  setDisabled(disable: boolean, props?: string[]) {
    this.itemRowList.setDisabled(disable, props);
  }

  setRequired(required: boolean, props?: string[]) {
    this.itemRowList.setRequired(required, props);
  }

  setBind(props: string | string[], key: string, value: any) {
    this.itemRowList.setBind(props, key, value);
  }

  setOptions(prop: string, options: { [key: string]: any }[]) {
    this.itemRowList.setOptions(prop, options);
  }

  setConfig(prop: string, config: YItemConfig) {
    this.itemRowList.setConfig(prop, config);
  }

  removeConfig(props: string | string[]) {
    this.itemRowList.removeConfig(props);
  }

  appendConfigBefore(prop: string, config: YItemConfig) {
    this.itemRowList.appendConfigBefore(prop, config);
  }

  appendConfigAfter(prop: string, config: YItemConfig) {
    this.itemRowList.appendConfigAfter(prop, config);
  }

  replaceConfig(prop: string, config: YItemConfig) {
    this.itemRowList.replaceConfig(prop, config);
  }

  removeRow(id: string | number) {
    if (this.data.id === id && this.prev) {
      if (this.next) {
        this.next.prev = this.prev;
      }
      this.prev.next = this.next;
    }
  }

  appendRowBefore(
    id: string | number,
    config: YItemRow | YItemConfig | YItemRow[]
  ) {
    if (this.data.id === id && this.prev) {
      let node: ItemConfig | ItemRow | ItemRowList | null = null;
      if ('type' in config) {
        node = new ItemConfig(
          config as YItemConfig,
          null,
          this.prev,
          this.form
        );
      } else if ('children' in config) {
        node = new ItemRow(config as YItemRow, null, this.prev, this.form);
      } else if (Array.isArray(config)) {
        const itemRowList = new ItemRowList(null, this.prev, this.form);
        config.forEach((item) => itemRowList.add(item));
        node = itemRowList;
      }
      if (node) {
        node.next = this;
        this.prev.next = node;
        return node;
      }
    }
  }

  appendRowAfter(
    id: string | number,
    config: YItemConfig | YItemRow | YItemRow[]
  ) {
    if (this.data.id === id) {
      let node: ItemConfig | ItemRow | ItemRowList | null = null;
      if ('type' in config) {
        node = new ItemConfig(config as YItemConfig, null, this, this.form);
      } else if ('children' in config) {
        node = new ItemRow(config as YItemRow, null, this, this.form);
      } else if (Array.isArray(config)) {
        const itemRowList = new ItemRowList(null, this, this.form);
        config.forEach((item) => itemRowList.add(item));
        node = itemRowList;
      }
      if (node) {
        if (this.next) {
          this.next.prev = node;
        }
        node.next = this.next;
        this.next = node;
      }
    }
  }

  getItemConfigs() {
    return this.itemRowList.getItemConfigs();
  }

  getRows() {
    const itemRows: YItemRow[] = [this.data];
    return itemRows.concat(this.itemRowList.getRows());
  }
}
